<?
/**
 * @author Leonardo Alberto Celis, Mario Garcia 
 * @name Oh!DB
 * @desc Wrapper for ADODB
 * @copyright 2005-2007 (c) Leonardo Alberto Celis
 * @email celisla@hotmail.com
 *
 * @todo I've to put some examples in all the methods!
 *
 * @updated: 01:12 05/05/2007
 *
 */

class ohdb
{
	// the ADODB object connection
	public $oADODB			= '';
	public $Table			= "";
	public $PrimaryKey		= "";
	public $Order			= "";
	public $joins			= array();
	public $filters		= array();
	public $Debug			= false;
	public $LogicField     = '';
	public $ChildsTables   = array();
	public $xmlSQL         = "";
	public $sql			= "";
	public $bCache			= false;
	public $nCacheTime		= 0;
	public $bFirstRegister	= false;
	public $bLastRegister	= false;
	// if is active records delete becomes logic
	public $bLogic			= false;
	// to upper
	public $bUpper 			= false;
	// validations
	public $RelatedTables   = array();
	// check relations
	//public $bCheckRelations = false;
	public $sCodeErrorRelations = '';
	//check for this fields
	public $sDuplicatedField = '';
	public $sCodeErrorDuplicated = '';
	// navigations constants
	public $nav_first 		= 1;
	public $nav_next 		= 2;
	public $nav_prev 		= 4;
	public $nav_last 		= 8;
	public $Limit 			= 0;
	public $Offset			= 0;
	public $iLastID			= 0;
	// private properties
	public $Fields			= "";
	private $DefaultField   = "";
	//Array con los metaData de las columnas
	protected $aMetaColumns;
	//Array con las metaRules
	protected $aMetaRules;
	//Array con los campos de la tabla $this->Table
	private $aFields;
	//String con los datos adicionales para realizar el join
	protected $sJoinFields;
	// xml dom object
	public $oDomIt = null;
	// validation object
	public $oValidation = null;
	// recycled
	public $oRecycled = null;


	function __construct($oADODB = null)
	{
		$this->oADODB = $oADODB;
	}

	function __destruct()
	{

	}

	/**
	 * @author Leonardo Alberto Celis
	 * @desc ADODB Connection
	 *
	 * @todo handled multiple objects connections
	 *
	 */
	function connectTo()
	{
		// if debug is active show the error message
		if ($this->Debug)
		{
			$this->oADODB->debug = true;
		}

		return $this->oADODB;
	}


	/**
	 * @author Leonardo Alberto Celis
	 * @desc get all the selected rows by filters and joins
	 *
	 */
	function getAll()
	{
		$sSQL = 'SELECT ';

		// if it are fields...
		if ($this->Fields != '')
		{
			if (!is_array($this->aFields))
			{
				$aFieldsTmp = split(",", $this->Fields);

				$sFields = "";
				foreach($aFieldsTmp as $sKey => $aValue){
					$sFields .= ",$this->Table.$aValue";
				}

				$this->Fields = substr($sFields,1);
			}

			$sSQL .= $this->Fields;

			if ($this->sJoinFields != '' && $this->sJoinFields != null)
			{
				$sSQL .=  $this->sJoinFields;
			}

		}
		else
		{
			$sSQL .= '*';
		}

		$sSQL .= " FROM ".$this->Table;


		return $this->RunSQL($sSQL);
	}


	/**
	 * @author Leonardo Alberto Celis
	 * @desc get max id
	 *
	 */
	function getMaxID()
	{
		$this->clean();
		return $this->RunSQL("SELECT MAX(" . $this->PrimaryKey . ") AS MaxID FROM " . $this->Table)->fields['MaxID'];
	}


	/**
	 * @author Leonardo Alberto Celis
	 * @desc get min id
	 *
	 */
	function getMinID()
	{
		$this->clean();
		return $this->RunSQL("SELECT MIN(" . $this->PrimaryKey . ") AS MinID FROM " . $this->Table)->fields['MinID'];
	}



	/**
	 * @author Leonardo Alberto Celis
	 * @desc get one row by id
	 *
	 */
	public function getOne($id)
	{
		$this->clean();

		$this->addFilter($this->PrimaryKey, "=", $id);

		return $this->getAll();
	}

	/**
	 * @author Leonardo Alberto Celis
	 * @desc delete the row
	 *
	 */
	function delete($id)
	{
		// logic delete
		if ($this->bLogic)
		{
			$this->deleteLogic($id);
		}
		else
		{
			$this->clean();
			$sSQL = "DELETE FROM ".$this->Table." WHERE ".$this->PrimaryKey." = ".$id;

			return $this->RunSQL($sSQL);
		}
	}

	/**
	 * @author Leonardo Alberto Celis
	 * @desc delete the selected rows by filters
	 *
	 */
	public function deleteAll()
	{
		$this->cleanJoins();
		$sSQL = "DELETE FROM " . $this->Table;

		return $this->RunSQL($sSQL);
	}


	/**
	 * @author Leonardo Alberto Celis
	 * @desc logic delete
	 *
	 */
	function deleteLogic($id)
	{
		$data[$this->PrimaryKey] = $id;
		$data[$this->LogicField] = '0';

		$this->save($data);

		$this->cascadeDeleteLogic($this, $this->PrimaryKey, $id);
	}


	/**
	 * @author Leonardo Alberto Celis
	 * @desc handled transactions
	 *
	 */
	public function startTransaction()
	{
		$connect = $this->connectTo();

		$connect->StartTrans();
	}
	public function endTransaction()
	{
		$connect = $this->connectTo();
		return $connect->CompleteTrans();
	}

	/**
	 * @author Leonardo Alberto Celis
	 * @desc Cascade logic delete
	 *
	 * @todo Change the Execute to RunSQL
	 */
	function cascadeDeleteLogic($pobjTable, $pKey, $pId)
	{
		// get the adodb object connection
		$connect = $this->connectTo();

		// set the logic field in 0
		$data[$this->LogicField] = '0';

		if (count($pobjTable->ChildsTables) > 0 && $pobjTable->ChildsTables != '')
		{
			foreach( $pobjTable->ChildsTables as $value )
			{
				$objTable = new $value;

				$objTable->addFilter($pKey, "=", $pId);

				$rsChilds = $objTable->getAll();

				if (!$rsChilds->EOF)
				{
					while (!$rsChilds->EOF)
					{
						$connect->AutoExecute($objTable->Table, $data, 'UPDATE', $pKey . '=' . $pId);

						$objTable->cascadeDeleteLogic($objTable, $objTable->PrimaryKey, $rsChilds->fields[$objTable->PrimaryKey], 0);

						$rsChilds->MoveNext();
					}
				}
			}
		}
	}


	/**
	 * @author Leonardo Alberto Celis
	 * @desc Retrieved from Recycled
	 *
	 * @todo This has to be in a Recycled object
	 *
	 */
	function retrieveFromRecycled($pobjTable, $pId)
	{
		$oRecycled = $this->oRecycled;

		$connect = $this->connectTo();

		$data[$this->LogicField] = '1';

		if (count($pobjTable->ChildsTables) > 0 && $pobjTable->ChildsTables != '')
		{
			foreach( $pobjTable->ChildsTables as $value )
			{
				$objTable = new $value;

				$objTable->addFilter($pobjTable->PrimaryKey, "=", $pId);

				$rsChilds = $objTable->getAll();

				if (!$rsChilds->EOF)
				{
					while (!$rsChilds->EOF)
					{
						$oRecycled->addFilter('varPapTabla', '=', $objTable->Table, null, 'AND');
						$oRecycled->addFilter('varPapCampoClave', '=', $objTable->PrimaryKey, null, 'AND');
						$oRecycled->addFilter('intPapRegID', '=', $rsChilds->fields[$objTable->PrimaryKey], null);

						$rsDeleted = $oRecycled->getAll();

						if ($rsDeleted->EOF)
						{
							$connect->AutoExecute($objTable->Table, $data, 'UPDATE', $pobjTable->PrimaryKey . '=' . $pId);
						}

						$objTable->retrieveFromRecycled($objTable, $rsChilds->fields[$objTable->PrimaryKey]);

						$rsChilds->MoveNext();
					}
				}
			}
		}
	}

	/**
	 * @author Leonardo Alberto Celis
	 * @desc this is the core baby!
	 *
	 */
	public function RunSQL($sql)
	{
		$connect = $this->connectTo();

		$sql = $this->buildJoins($sql);

		$sql = $this->buildFilters($sql);

		$sql = $this->buildOrder($sql);

		// if it the cache is on
		if ($this->bCache)
		{
			if ($this->Limit != 0 || $this->Offset != 0)
			{
				$rs = $connect->CacheSelectLimit($this->nCacheTime, $sql, $this->Limit, $this->Offset);
			}
			else
			{
				$rs = $connect->CacheExecute($this->nCacheTime, $sql);
			}

		}
		else
		{

			if ($this->Limit != 0 || $this->Offset != 0)
			{
				$rs = $connect->SelectLimit($sql, $this->Limit, $this->Offset);
			}
			else
			{
				$rs = $connect->Execute($sql);
			}
		}

		$this->sql = $sql;

		if (!$rs)
		{
			if ($this->Debug)
			{
				echo $connect->ErrorMsg();
				die();
			}
		}
		else
		{
			$this->AffectedRows = $connect->Affected_Rows();
			return $rs;
		}


	}


	/**
	 * @author Leonardo Alberto Celis
	 * @desc Build the SQL statement based on relations with other tables
	 *
	 */
	private function buildJoins($sql)
	{
		$joins = $this->joins;

		if (count($joins) > 0 && $joins != '')
		{
			foreach ($joins as $join)
			{
				// si viene un join
				if ($join['direction'] != null && $join['direction'] != '')
				{
					$sql .= ' ' . $join['direction'] . ' JOIN ' . $join['table'] .' ';
				}
				else
				{
					$sql .= ' INNER JOIN ' . $join['table'] .' ';
				}

				if (isset($join['primary']))
				{
					$table = $this->Table;
					if (stripos($join['primary'], ".") !== false ) $table = '';
					$sql .= ' ON ' . $table . '.' . $join['primary'] . '=' . $join['table'] . '.' . $join['foreign'] . ' ';
				}

			}
		}

		return $sql;
	}

	/**
	 * @author Leonardo Alberto Celis
	 * @desc Build the filters
	 *
	 */
	private function buildFilters($sql)
	{
		$filters = $this->filters;

		if (($filters != '' && count($filters) > 0) || $this->bLogic) $sql .= " WHERE ";

		if ($this->bLogic)
		{
			$sql .= $this->Table . "." . $this->LogicField . " = 1 ";

			if ($filters != '' && count($filters) > 0)
			{
				$sql .= " AND ";
			}
		}

		$filters = $this->filters;

		if ($filters != '' && count($filters) > 0)
		{
			$i = 0;

			foreach ($filters as $filter)
			{
				if ($filter['function'] != '' ||  $filter['function'] != null)
				{
					$sql .= " " . $filter['function'] . '(' . $filter['field'] . ") " . $filter['condition'] . " '" . $filter['value'] . "'";
				}
				else
				{
					$sql .= " " . $filter['field'] . " " . $filter['condition'] . " '" . $filter['value'] . "'";
				}

				if ($i < count($filters)-1)
				{
					if (isset($filter['operator']) && ($filter['operator'] != '' || $filter['operator'] != null))
					{
						$sql .= ' ' . $filter['operator'];
					}
					else
					{
						$sql .= ' AND';
					}
				}

				$i++;
			}
		}

		return $sql;
	}

	/**
	 * @author Leonardo Alberto Celis
	 * @desc Build the orders
	 *
	 */
	private function buildOrder($sql)
	{
		if (is_array($this->Order))
		{
			$sql .= " ORDER BY ";
			$sField = '';

			foreach($this->Order as $sKey ){
				$sField .= ",$sKey" ;
			}

			$sql .= substr($sField,1);
		}

		return $sql;
	}


	/**
	 * @author Leonardo Alberto Celis
	 * @desc get the first row
	 *
	 */
	function getFirst()
	{
		$sSQL = "SELECT * FROM ".$this->Table . " order by " . $this->PrimaryKey . " LIMIT 0,1";
		$this->Limit = 0;

		return $this->RunSQL($sSQL);
	}


	/**
	 * @author Leonardo Alberto Celis
	 * @desc count rows
	 *
	 */
	function getCount()
	{
		$sSQL = "SELECT COUNT(*) AS COUNT FROM ".$this->Table;

		$rs = $this->RunSQL($sSQL);

		if ($rs->EOF)
		{
			return 0;
		}
		else
		{
			return $rs->fields['COUNT'];
		}
	}

	/**
	 * @author Leonardo Alberto Celis
	 * @desc sum all the values from the given field
	 *
	 */
	function getSum($field)
	{
		$this->clean();
		$sSQL = "SELECT SUM(" . $field . ") AS TOTAL FROM ".$this->Table;
		return $this->RunSQL($sSQL);
	}

	/**
	 * @author Leonardo Alberto Celis
	 * @desc check for duplicated rows
	 *
	 */
	public function checkDuplicated ($id = null, $name = null)
	{
		// clone object
		$o = $this;

		// check for duplicated register
		if ($this->sCodeErrorDuplicated != '' && $this->sDuplicatedField != '')
		{
			$o->addFilter($this->sDuplicatedField, '=', $name);
			// if the id is specified then check for all except the id
			if ($id != '') $o->addFilter($this->PrimaryKey, '<>', $id);
			$rs = $o->getAll();

			if (!$rs->EOF)
			{
				return false;
			}
			else
			{
				return true;
			}
		}

		return false;
	}



	/**
	 * @author Leonardo Alberto Celis
	 * @desc the other core!
	 *
	 * @todo Unified save and RunSQL methods
	 *
	 */
	function save($data)
	{
		$aSave = array();

		// if is not logic delete
		if ($data[$this->LogicField] == null || $data[$this->LogicField] == '')
		{
			if ($data[$this->LogicField] != '0')
			{
				$data[$this->LogicField] = 1;
			}
		}

		if (is_array($this->aFields))
		{
			foreach($this->aFields as $lnKey => $lsValue){
				$nombre = $this->aFields[$lnKey];
				$aSave[$nombre] = $data[$nombre];

				if (is_string($data[$nombre]) && $this->bUpper) $data[$nombre] = $this->str2Upper($data[$nombre]);

				if (is_string($data[$nombre]) && ($data[$nombre] == '' || is_null($data[$nombre]))) $data[$nombre] = "null";

				$aSave[$nombre] = $data[$nombre];
			}

			$data = $aSave;
		}

		// connection
		$connect = $this->connectTo();

		// for checkbox?
		/*foreach( $data as $key => $value)
		{
			if (strtolower($value) == 'on')
			{
				$data[$key] = '1';
			}
		}*/
		
		$ok = true;
		// if the primarykey has value
		if (isset($data[$this->PrimaryKey]) && $data[$this->PrimaryKey] != "null")
		{
			// update
			$ok = $connect->replace($this->Table, $data, $this->PrimaryKey, true);
			$this->iLastID = $data[$this->PrimaryKey];
		}
		else
		{
			// insert
			$ok = $connect->AutoExecute($this->Table, $data, 'INSERT');
			$this->iLastID = $connect->Insert_ID();
		}

		return $ok;
	}

	/**
	 * @author Leonardo Alberto Celis
	 * @desc Check if the register id exists
	 *
	 */
	function validateUnique($id)
	{
		$this->clean();
		$this->addFilter($this->PrimaryKey, "=", $id, null, null);
		$rs = $this->getAll();
		$this->clean();

		return !$rs->EOF;
	}


	/**
	 * @author Leonardo Alberto Celis
	 * @desc this is experimental, the xml query!
	 *
	 */
	function xmlQuery($pstrTag, $parrParams = array())
	{
		// the domit object, only this object!
		$success = $this->oDomIt->loadXML($this->xmlSQL, true);

		if ($success)
		{
			//use getElementsByTagName to gather all elements named "cd"
			$matchingNodes =& $this->oDomIt->getElementsByTagName($pstrTag);

			//if any matching nodes are found, echo to browser
			if ($matchingNodes != null)
			{
				$temp = $matchingNodes->item(0);
				$sql = $temp->getText();

				if (count($parrParams) > 0)
				{
					for ($i = 0; $i < count($parrParams); $i++)
					{
						$sql = str_replace('@param' . $i, $parrParams[$i], $sql);
					}
				}

				$connect = $this->connectTo();
				return $connect->Execute($sql);
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
	}


	/**
	 * @author Leonardo Alberto Celis
	 * @desc Clean objects properties
	 *
	 */
	function clean()
	{
		$this->JoinFields = null;
		$this->Order  = null;
		$this->sJoinFields  = null;
		$this->aFields = null;
		$this->Fields = null;
		$this->filters = null;
		$this->joins = null;
	}
	function cleanFilters()
	{
		$this->filters = null;
	}
	function cleanJoins()
	{
		$this->joins = null;
	}

	/**
	 * @author Mario Garcia
	 * @desc this is awesome!, get the schema for the given table
	 *
	 */
	function getMetaColumns()
	{

		// pacth for store procedure sync error
		//if( is_object($this->connectTo()->_queryID) ) mysqli_free_result($this->connectTo()->_queryID);

		$dataDictionary = NewDataDictionary($this->connectTo());

		if(!$this->Table) return array();

		$aMetaColumns =  $dataDictionary->MetaColumns($this->Table);

		$aFields = array();
		$sFields = "";
		foreach($aMetaColumns as $sKey => $aValue){
			$aFields[] =  $aValue->name;
			$sFields .= ",$this->Table.$aValue->name";
			if($aValue->primary_key){
				$this->PrimaryKey = $aValue->name;
			}

		}

		$this->aFields = $aFields;

		$this->Fields = substr($sFields,1);

		$this->aMetaColumns = $aMetaColumns;

		return $this->aMetaColumns;
	}

	/**
	 * @author Mario Garcia
	 * @desc this method is cancel, the validation rules must be in another class
	 *
	 */
	function initMetaRules()
	{
		// example:
		//$this->arrRules[] = "required,varOriNombre,El varOriNombre es requerido.";

		/*foreach($this->aMetaColumns  as $sKey => $aMetaColumn)
		{
			if($aMetaColumn->primary_key) continue;

			if($aMetaColumn->not_null )
			{
				$this->aMetaRules[] = "required,{$aMetaColumn->name}, Es requerido.";
			}

			switch($aMetaColumn->type)
			{
				case 'int':
				$this->aMetaRules[] = "digits_only,{$aMetaColumn->name},Ingrese un valor numerico.";
				break;

				//decimal,text,tinyint,date?
			}
		}*/
		return null;
	}


	/**
	 * @author Mario Garcia
	 * @desc validate metarules
	 *
	 */
	function validateMetaRules( $aValues)
	{
		return validateFields($aValues, $this->aMetaRules);
	}

	/**
	 * @author Mario Garcia
	 * @desc friendly method for add joins
	 *
	 */
	function addJoin($psTableName, $paKeys, $paReturnFields = null, $psDirection = null)
	{
		$aJoin =  array (
		'table' => $psTableName,
		'primary' => $paKeys[0],
		'foreign' => $paKeys[1],
		'direction' => $psDirection,
		);

		$this->joins[] = $aJoin;

		if ($paReturnFields != null || $paReturnFields != '')
		{
			foreach($paReturnFields as $sKey => $sValue)
			{
				if (stripos($sValue, ".") === false )
				{
					$this->sJoinFields .= ",$psTableName.$sValue";

				}
				else
				{
					$this->sJoinFields .= ",$sValue";
				}
			}
		}
		else
		{
			$this->sJoinFields .= ",{$psTableName}.*";
		}
	}


	/**
	 * @author Mario Garcia
	 * @desc friendly method for add filters
	 *
	 */
	function addFilter($psField, $psCriteria, $psValue, $psTableName = null, $psOperador = null, $psFunction = null)
	{
		if (is_null($psTableName))
		{
			$psTableName = $this->Table;
		}

		$aFilter = array (
		'field' => $psTableName.'.'.$psField,
		'condition' =>$psCriteria,
		'value' => $psValue
		);

		if(!empty($psOperador))
		{
			$aFilter['operator'] = $psOperador;
		}

		if(!empty($psFunction))
		{
			$aFilter['function'] = $psFunction;
		}

		$this->filters[] = $aFilter;

	}

	/**
	 * @author Mario Garcia
	 * @desc friendly method for add rules
	 *
	 */
	function addRules($psCriteria, $psFieldName, $psMessageError)
	{
		$this->aMetaRules[] = $psCriteria.','.$psFieldName.','.$psMessageError;
	}

	/**
	 * @author Mario Garcia
	 * @desc friendly method for add orders
	 *
	 */
	function addOrder($psTableName = null, $psField , $psDirection = null)
	{
		if ($psTableName == null) $psTableName = $this->Table;

		$this->Order[] = $psTableName.'.'.$psField.' '.$psDirection;
	}

	/**
	 * @author Leonardo Alberto Celis
	 * @desc get rows, but not a rs object, an array!
	 *
	 */
	function getOneToArray($id)
	{

		$rs = $this->getOne($id);

		if ($rs->EOF)
		{
			return array();
		}
		else
		{
			return $rs->GetRows();
		}
	}
	function getAllToArray()
	{
		$rs = $this->getAll();

		if ($rs->EOF)
		{
			return array();
		}
		else
		{
			return $rs->GetRows();
		}
	}

	/**
	 * @author Mario Garcia
	 * @desc init the meta, get the schema, empowered the object
	 *
	 */
	function initMeta()
	{
		//Este metodo carga en $this->aMetaColumns toda la info de la metadata
		//Tiene que ser llamado despues de inicializar $this->Table = "tblProOrigenes";
		//y tiene que ser llamado solo en el constructor
		$this->getMetaColumns();
		//luego de crear la metadata creo las metas rules
		$this->initMetaRules();
	}


	/**
	 * @author Mario Garcia
	 * @desc Execute a Store Procedure
	 *
	 */
	public function ExecuteSP($psSPName, $paSPParameters)
	{
		$lsSQLParm  = "";
		foreach ($paSPParameters as $lnKey){
			$lsSQLParm .= ",?";
		}

		$lsSQLParm = substr($lsSQLParm,1);
		$lsSQLSP = "CALL {$psSPName} ({$lsSQLParm})";
		$connect = $this->connectTo();
		$lmRS = $connect->Execute($lsSQLSP, $paSPParameters);


		return $lmRS;
	}

	/**
	 * @author Leonardo Alberto Celis
	 * @desc rows navigator
	 *
	 */
	public function navigator($piConst, $piID)
	{
		switch ($piConst)
		{
			case $this->nav_first:
				$this->cleanFilters();
				$this->Limit = 1;
				$this->addOrder(null, $this->PrimaryKey, "ASC");
				$rs = $this->getAll();

				if ($rs->EOF)
				{
					return $this->getRecordsetSchema($rs);
				}
				else
				{
					return $rs->getRows();
				}
				break;

			case $this->nav_next:
				$this->Limit = 1;
				$this->addFilter($this->PrimaryKey, ">", $piID);
				$rs = $this->getAll();

				if ($rs->EOF)
				{
					return $this->navigator($this->nav_first, null);
				}
				else
				{
					return $rs->GetArray(1);
				}
				break;

			case $this->nav_prev:
				$this->addFilter($this->PrimaryKey, "<", $piID);
				$rs = $this->getAll();

				if ($rs->EOF)
				{
					return $this->navigator($this->nav_last, null);
				}
				else
				{
					$rs->MoveLast();
					return $rs->GetArray(1);
				}
				break;

			case $this->nav_last:
				$this->cleanFilters();
				$this->Limit = 1;
				$this->addOrder(null, $this->PrimaryKey, "DESC");
				$rs = $this->getAll();

				if ($rs->EOF)
				{
					return $this->getRecordsetSchema($rs);
				}
				else
				{
					return $rs->getRows();
				}

				break;
		}
	}

	/**
	 * @name Mario Garcia
	 * @desc Get the recordset schema
	 *
	 */
	function getRecordsetSchema($poRs)
	{
		$arrFields = array();

		for($i=0; $i < $poRs->_numOfFields; $i++ )
		{
			$arrFields[$poRs->FetchField($i)->name] = '';
		}

		return array($arrFields);
	}

	/**
	 * @name Leonardo Alberto Celis
	 * @desc check for relations in another tables
	 *
	 */
	public function checkRelations($id)
	{
		$ok = true;

		// check for relationed tables
		if (count($this->ChildsTables) > 0 && $this->ChildsTables != '')
		{
			foreach( $this->ChildsTables as $value )
			{
				$oTable = new $value;

				$oTable->addFilter($this->PrimaryKey, "=", $id, null, null);

				$rsChilds = $oTable->getAll();

				if (!$rsChilds->EOF)
				{
					$ok &= false;
				}
			}
		}

		// check for related tables
		if (count($this->RelatedTables) > 0 && $this->RelatedTables != '')
		{
			foreach( $this->RelatedTables as $value )
			{
				$oTable = new $value;

				$oTable->addFilter($this->PrimaryKey, "=", $id, null, null);

				$rsChilds = $oTable->getAll();

				if (!$rsChilds->EOF)
				{
					$ok &= false;
				}
			}
		}

		return $ok;
	}


	/**
	 * @author Leonardo Alberto Celis
	 * @desc Change to Upper only the alphabetical characters
	 *
	 */
	private function str2Upper($psString)
	{
		$psString = mb_convert_case($psString, MB_CASE_UPPER, "UTF-8");

		return $psString;
	}
}
?>